package osc;

import java.nio.ByteBuffer;

public class OSCMessage {

	public final static char INTEGER = 'i';
	public final static char STRING = 's';
	public final static char BLOB = 'b';
	public final static char FLOAT = 'f';

	private String target = null;
	private String parametersTemplate = null;
	private Object[] parameters = null;

	private byte[] bufferBytes = new byte[128];
	private ByteBuffer buffer = ByteBuffer.wrap(bufferBytes);

	public OSCMessage() {

	}

	public OSCMessage(String targetValue, String parametersTemplateValue) {
		this.target = targetValue;
		this.parametersTemplate = parametersTemplateValue;
		if (parametersTemplateValue != null && parametersTemplateValue.length() > 0) {
			this.parameters = new Object[parametersTemplateValue.length()];
		}
	}

	public String toString() {
		StringBuffer output = new StringBuffer();
		output.append(this.target);
		if (this.parameters != null) {
			output.append(" ");
			output.append(this.parametersTemplate);
			for (Object parameter : parameters) {
				output.append(" <");
				output.append(parameter);
				output.append(">");
			}
		}
		return output.toString();
	}

	public String getParametersTemplate() {
		return this.parametersTemplate;
	}

	public void setParametersTemplate(String parametersTemplateValue) {
		this.parametersTemplate = parametersTemplateValue;
	}

	public String getTarget() {
		return this.target;
	}

	public void setTarget(String targetValue) {
		this.target = targetValue;
	}

	// private int getByteArrayMessageSize() {
	// int byteArrayMessageSize = target.length() + target.length() % 4;
	// if (this.parametersTemplate != null) {
	// int stringLength = 0;
	// int blobLength = 0;
	// for (int i = 0; i < this.parametersTemplate.length(); i++) {
	// switch (this.parametersTemplate.charAt(i)) {
	// case OSCMessage.STRING:
	// stringLength = ((String) this.parameters[i]).length() + 1;
	// stringLength += stringLength % 4;
	// byteArrayMessageSize += stringLength;
	// break;
	// case OSCMessage.BLOB:
	// blobLength = ((byte[]) this.parameters[i]).length + 4;
	// blobLength += blobLength % 4;
	// byteArrayMessageSize += blobLength;
	// break;
	// default:
	// byteArrayMessageSize += 4;
	// }
	// }
	// }
	// return byteArrayMessageSize;
	// }

	public byte[] toByteArray() {

		buffer.clear();
		buffer.put(this.target.getBytes());
		buffer.position(buffer.position() + 4 - buffer.position() % 4);

		if (this.parametersTemplate != null) {

			buffer.put((byte) ',');
			buffer.put(this.parametersTemplate.getBytes());
			buffer.position(buffer.position() + 4 - buffer.position() % 4);

			for (int i = 0; i < this.parametersTemplate.length(); i++) {
				switch (this.parametersTemplate.charAt(i)) {
				case OSCMessage.INTEGER:
					buffer.putInt((Integer) this.parameters[i]);
					break;
				case OSCMessage.STRING:
					buffer.put(((String) this.parameters[i]).getBytes());
					buffer.position(buffer.position() + 4 - buffer.position() % 4);
					break;
				case OSCMessage.FLOAT:
					buffer.putFloat((Float) this.parameters[i]);
					break;
				case OSCMessage.BLOB:
					buffer.put((byte[]) this.parameters[i]);
					buffer.position(buffer.position() + 4 - buffer.position() % 4);
					break;
				}
			}
		}

		return bufferBytes;
	}

	public Object[] getParameters() {
		return parameters;
	}

	public void setParameters(Object[] parametersValue) {
		this.parameters = parametersValue;
	}

	public Object getParameter(int index) {
		return this.parameters != null ? this.parameters[index] : null;
	}

	public void setParameter(int index, Object parameterValue) {
		if (this.parameters != null) {
			this.parameters[index] = parameterValue;
		}
	}

}
